home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
comm
/
mail
/
Mutt089src.lha
/
Mutt-0.89i-AMIGA
/
src
/
rfc1524.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-28
|
17KB
|
677 lines
/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* rfc1524 defines a format for the Multimedia Mail Configuration, which
* is the standard mailcap file format under Unix which specifies what
* external programs should be used to view/compose/edit multimedia files
* based on content type.
*
* This file contains various functions for implementing a fair subset of
* rfc1524.
*/
#include "mutt.h"
#include "rfc1524.h"
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
/* The command semantics include the following:
* %s is the filename that contains the mail body data
* %t is the content type, like text/plain
* \% is %
* Unsupported rfc1524 parameters: these would probably require some doing
* by mutt, and can probably just be done by piping the message to metamail
* %{parameter} is replaced by the parameter value from the content-type field
* %n is the integer number of sub-parts in the multipart
* %F is "content-type filename" repeated for each sub-part
*
* In addition, this function returns a 0 if the command works on a file,
* and 1 if the command works on a pipe.
*/
int rfc1524_expand_command (BODY *a, char *filename, char *type,
char *command, int clen)
{
int x=0,y=0;
int needspipe = TRUE;
char buf[LONG_STRING];
while (command[x] && x<clen && y<sizeof(buf)) {
if (command[x] == '\\') {
x++;
buf[y++] = command[x++];
}
else if (command[x] == '%') {
x++;
if (command[x] == '{') {
char param[STRING];
int z = 0;
char *ret = NULL;
x++;
while (command[x] && command[x] != '}' && z<sizeof(param))
param[z++] = command[x++];
param[z] = '\0';
dprint(2,(debugfile,"Parameter: %s Returns: %s\n",param,ret));
ret = mutt_get_parameter(param,a->parameter);
dprint(2,(debugfile,"Parameter: %s Returns: %s\n",param,ret));
z = 0;
while (ret && ret[z] && y<sizeof(buf))
buf[y++] = ret[z++];
}
else if (command[x] == 's' && filename != NULL)
{
char *fn = filename;
while (*fn && y < sizeof (buf))
buf[y++] = *fn++;
needspipe = FALSE;
}
else if (command[x] == 't')
{
while (*type && y < sizeof (buf))
buf[y++] = *type++;
}
x++;
}
else
buf[y++] = command[x++];
}
buf[y] = '\0';
strfcpy (command, buf, clen);
return needspipe;
}
int rfc1524_mailcap_parse (BODY *a,
char *filename,
char *type,
rfc1524_entry *entry,
int opt)
{
FILE *fp = NULL;
char buf[LONG_STRING];
char basetype[STRING];
char *ch;
int found = FALSE;
int match = TRUE;
int wrap = FALSE;
int copiousoutput = FALSE;
int composecommand = FALSE;
int editcommand = FALSE;
int printcommand = FALSE;
int x = 0, y = 0;
int btlen = 0;
/* rfc1524 mailcap file is of the format:
* base/type; command; extradefs
* type can be * for matching all
* base with no /type is an implicit wild
* command contains a %s for the filename to pass, default to pipe on stdin
* extradefs are of the form:
* def1="definition"; def2="define \;";
* line wraps with a \ at the end of the line
* # for comments
*/
if ((fp = fopen (filename, "r")) != NULL)
{
/* copy base type into basetype */
x = 0;
while (type[x] && x < sizeof (basetype) && type[x] != '/')
{
basetype[x] = type[x];
x++;
}
basetype[x] = '\0';
dprint (2, (debugfile, "mailcap basetype: %s\n", basetype));
btlen = x;
while (!found && fgets (buf, sizeof (buf), fp))
{
/* Strip comments (ie, everything after #, but not \# */
if ((ch = strchr (buf, '#')))
if ((ch == buf) || (*(ch-1) != '\\'))
*ch = '\0';
/* Strip trailing white space */
y = strlen (buf);
y = (y ? y - 1 : 0);
while (y && (buf[y] == ' ' || buf[y] == '\t' || buf[y] == '\n'))
buf[y--] = '\0';
/* handle line wrap */
if (buf[y] == '\\')
wrap = TRUE;
else
wrap = FALSE;
while (wrap && fgets (buf + strlen (buf) - 1, sizeof (buf) - strlen (buf),fp))
{
if ((ch = strchr (buf,'#')))
{
if (*(ch-1) != '\\')
*ch = '\0';
}
y = strlen (buf);
y = (y ? y - 1 : 0);
while (buf[y] == ' ' || buf[y] == '\t' || buf[y] == '\n')
buf[y--] = '\0';
if (buf[y] == '\\')
wrap = TRUE;
else
wrap = FALSE;
}
dprint (2, (debugfile, "mailcap entry: %s\n", buf));
if (!strncasecmp (buf, type, strlen (type)) && (buf[strlen (type)] == ';'))
found = TRUE;
else
{
/* Check * case */
if (strncmp (buf, basetype, btlen-1) == 0)
{
/* check * wildcard */
if (buf[btlen] && buf[btlen+1] && buf[btlen] == '/' &&
buf[btlen+1] == '*')
found = TRUE;
/* check implicit wild */
else if (buf[btlen] && buf[btlen] == ';')
found = TRUE;
}
}
/* Parse the found line for the information we need */
if (found)
{
char *tok;
int z = 0, i = 0;
char token[STRING];
/* first field is content type, already checked, so skip */
while (z < sizeof (buf) && buf[z] && buf[z] != ';')
z++;
z++;
/* next field is the command */
while (z < sizeof (buf) && i < sizeof (token) && buf[z] &&
!(buf[z] == ';' && buf[z-1] != '\\'))
token[i++] = buf[z++];
token[i] = '\0';
z++;
tok = mutt_skip_whitespace (token);
if (entry)
entry->command = safe_strdup (tok);
/* parse the optional fields */
/* next field is the command */
i = 0;
while (z < sizeof (buf) && i < sizeof (token) && buf[z] &&
!(buf[z] == ';' && buf[z-1] != '\\'))
token[i++] = buf[z++];
token[i] = '\0';
z++;
while (token[0])
{
tok = mutt_skip_whitespace (token);
dprint (2, (debugfile, "token: %s\n", tok));
if (!strcasecmp (tok, "needsterminal"))
{
if (entry)
entry->needsterminal = TRUE;
}
else if (!strcasecmp (tok, "copiousoutput"))
{
copiousoutput = TRUE;
if (entry)
entry->copiousoutput = TRUE;
}
else if (!strncasecmp (tok, "composetyped", 12))
{
/* this compare most occur before compose to match correctly */
/* this isn't particularly well specified in the rfc, so skip it */
}
else if (!strncasecmp (tok, "compose", 7))
{
tok += 7;
tok = mutt_skip_whitespace (tok);
if (*tok == '=')
{
composecommand = TRUE;
if (entry)
{
tok = mutt_skip_whitespace (++tok);
safe_free ((void **) &entry->composecommand);
entry->composecommand = safe_strdup (tok);
}
}
else
mutt_error ("Improperly formated mailcap entry for type %s", type);
}
else if (!strncasecmp (tok, "print", 5))
{
tok+=5;
tok = mutt_skip_whitespace (tok);
if (*tok == '=')
{
printcommand = TRUE;
if (entry)
{
tok = mutt_skip_whitespace (++tok);
safe_free ((void **) &entry->printcommand);
entry->printcommand = safe_strdup(tok);
}
}
else
mutt_error("Improperly formated mailcap entry for type %s", type);
}
else if (!strncasecmp (tok, "edit", 4))
{
tok+=4;
tok = mutt_skip_whitespace (tok);
if (*tok == '=')
{
editcommand = TRUE;
if (entry)
{
tok = mutt_skip_whitespace (++tok);
safe_free((void **) &entry->editcommand);
entry->editcommand = safe_strdup(tok);
}
}
else
mutt_error ("Improperly formated mailcap entry for type %s", type);
}
else if (